package commons.utils.primitive_geom;

import commons.spatialindex.I_SpatialIndexable;

public class Segment_d implements I_SpatialIndexable {

	public Point_d pt1, pt2;

	public Segment_d () {
		this (new Point_d(0, 0), new Point_d(0, 0));
	}

	public Segment_d (Segment_d seg) {
		this.pt1 = seg.pt1;
		this.pt2 = seg.pt2;
	}
	public Segment_d (Point_d pt1, Point_d pt2) {
		this.pt1 = pt1;
		this.pt2 = pt2;
	}
	public Segment_d (double x1, double y1, double x2, double y2) {
		this (new Point_d(x1, y1), new Point_d(x2, y2));
	}

	// Rend le segment indépendant avec 2 point extrémité qui lui sont propres
	public void supprLinkCoord() {
		pt1 = new Point_d(pt1);
		pt2 = new Point_d(pt2);
	}

	@Override
	public String toString() {
		return Segment_d.getStringOf(this);
	}
	
	public static String getStringOf(Segment_d seg) {
		return "Segment : (" + seg.pt1.x + " , " + seg.pt1.y + ") -> (" + seg.pt2.x + " , " + seg.pt2.y + ")  lg = " + seg.getLength();
	}

	public void setCoord(double x1, double y1, double x2, double y2) {
		this.pt1.x = x1;
		this.pt1.y = y1;
		this.pt2.x = x2;
		this.pt2.y = y2;
	}

	public void takeCoordFrom(Point_d pt1, Point_d pt2) {
		this.pt1.x = pt1.x;
		this.pt1.y = pt1.y;
		this.pt2.x = pt2.x;
		this.pt2.y = pt2.y;
	}

	public void takeCoordFrom(Segment_d s) {
		this.pt1.x = s.pt1.x;
		this.pt1.y = s.pt1.y;
		this.pt2.x = s.pt2.x;
		this.pt2.y = s.pt2.y;
	}

	public void translate (double dx, double dy) {
		pt1.x += dx;
		pt1.y += dy;
		pt2.x += dx;
		pt2.y += dy;
	}

	public void decalePerpendiculairement(double decalage, boolean bDroite) {
		double l = getLength();
		if (l==0) return;
		
		double u, v;
		u = (pt2.x-pt1.x) / l;
		v = (pt2.y-pt1.y) / l;

		double u_perp, v_perp;
		if (bDroite) {
			u_perp = v;
			v_perp = -u;
		} else {
			u_perp = -v;
			v_perp = u;
		}

		pt1.x += u_perp * decalage;
		pt2.x += u_perp * decalage;

		pt1.y += v_perp * decalage;
		pt2.y += v_perp * decalage;
	}

	// Interface I_SpatialIndexable
	@Override
	public double getXMin() {return Math.min(pt1.x, pt2.x);}
	@Override
	public double getXMax() {return Math.max(pt1.x, pt2.x);}
	@Override
	public double getYMin() {return Math.min(pt1.y, pt2.y);}
	@Override
	public double getYMax() {return Math.max(pt1.y, pt2.y);}
	@Override
	public Rect_d getRectEmprise() {return new Rect_d(pt1, pt2);}

	
	public Point_d getCenter() {return new Point_d( (pt1.x + pt2.x)/2 , (pt1.y + pt2.y)/2 );}

	public boolean isVertical() {return pt1.x == pt2.x;}
	public boolean isHorizontal() {return pt1.y == pt2.y;}
	public boolean isPoint() {return pt1.x == pt2.x && pt1.y == pt2.y;}

	public double getLength() {return Math.sqrt( (pt2.x-pt1.x)*(pt2.x-pt1.x) + (pt2.y-pt1.y)*(pt2.y-pt1.y) );}
	public double getLengthSq() {return (pt2.x-pt1.x)*(pt2.x-pt1.x) + (pt2.y-pt1.y)*(pt2.y-pt1.y) ;}

	public boolean equals(Segment_d seg) {return this==seg;}
	public boolean equalsCoord(Segment_d seg) {return (this.pt1.equalsXY(seg.pt1) && this.pt2.equalsXY(seg.pt2)) || (this.pt1.equalsXY(seg.pt2) && this.pt2.equalsXY(seg.pt1));}

	public boolean hasThisExtremity(Point_d pt) {return this.pt1.equalsXY(pt) || this.pt2.equalsXY(pt);}
	public boolean hasCommonExtremity(Segment_d seg) {return this.hasThisExtremity(seg.pt1) || this.hasThisExtremity(seg.pt2);}
	public Point_d getCommonExtremity(Segment_d seg) {
		if (this.hasThisExtremity(seg.pt1))
			return seg.pt1;
		if (this.hasThisExtremity(seg.pt2))
			return seg.pt2;
		return null;
	}
		
}
